package com.pocket.insight.base.context;

import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Field;
import java.util.Map;

/**
 * 描述：
 *
 * @author shuize
 * @create 2024/12/4
 */
@Component
public class SpringContext implements ApplicationContextAware {
    private static ApplicationContext applicationContext;

    public void setApplicationContext(ApplicationContext applicationContext) {
        SpringContext.applicationContext = applicationContext;
        setRunContext(applicationContext);
    }

    private void setRunContext(ApplicationContext applicationContext) {
        Boolean runInUnitTest = applicationContext.getEnvironment().getProperty("run-in-unit-test", Boolean.class);
        if (BooleanUtils.isTrue(runInUnitTest)) {
            Field field = ReflectionUtils.findField(RunContext.class, "RUN_IN_UNIT_TEST");
            ReflectionUtils.makeAccessible(field);
            ReflectionUtils.setField(field, RunContext.class, Boolean.valueOf(true));
            field.setAccessible(false);
        }
    }

    public static ApplicationContext getApplicationContext() {
        checkApplicationContext();
        return applicationContext;
    }

    public static <T> T getBean(String name) {
        checkApplicationContext();
        return (T) applicationContext.getBean(name);
    }

    public static <T> T getBean(Class<T> clazz) {
        checkApplicationContext();
        Map beanMaps = applicationContext.getBeansOfType(clazz);
        if (beanMaps != null && !beanMaps.isEmpty()) {
            return (T) beanMaps.values().iterator().next();
        }
        return null;
    }


    private static void checkApplicationContext() {
        if (applicationContext == null) {
            throw new IllegalStateException("applicationContext未注入,请在applicationContext.xml中定义SpringContextHolder");
        }
    }


    public static void registerBean(String beanName, Object object) {
        ConfigurableListableBeanFactory beanFactory = ((AnnotationConfigServletWebServerApplicationContext) applicationContext).getBeanFactory();
        String nameToUse = StringUtils.isNoneBlank(new CharSequence[]{beanName}) ? beanName : object.getClass().getName();
        beanFactory.registerSingleton(nameToUse, object);
    }
}
